from datetime import datetime
from flask import render_template, flash, redirect, url_for, current_app, request, make_response
from . import main
from ..models import Permission, User, Role, Post, PostType
from flask import abort
from .forms import EditProfileForm, PostTypeForm, EditProfileAdminForm, PostForm, SearchPosts
from flask_login import current_user, login_required
from ..decorators import admin_required, permission_required
from app import db
from bs4 import BeautifulSoup


@main.route('/', methods=['GET', 'POST'])
def index():
    searchform = SearchPosts()
    page = request.args.get('page', 1, type=int)
    if searchform.validate_on_submit():
        search = searchform.content.data
        pagination = Post.query.whoosh_search(search).order_by(Post.timestamp.desc()).paginate(
            page, per_page=current_app.config['FLASKY_POSTS_PER_PAGE'], error_out=False
        )
        count = 0
        for post in pagination.items:
            count += 1
        # 转换为str 才可以 输出
        flash("搜索出了 "+str(count)+' 条关于 '+search+' 的结果')
    else:
        pagination = Post.query.order_by(Post.timestamp.desc()).paginate(
            page, per_page=current_app.config['FLASKY_POSTS_PER_PAGE'], error_out=False
        )
    posts = pagination.items
    return render_template('index.html', posts=posts, pagination=pagination, searchform=searchform)


@main.route('/user/<username>')
def user(username):
    form = SearchPosts()
    user = User.query.filter_by(username=username).first()
    if user is None:
        abort(404)
    posts = user.posts.order_by(Post.timestamp.desc()).all()
    return render_template('user.html', user=user, posts=posts)


@main.route('/new_posttype', methods=['GET', 'POST'])
@login_required
def new_posttype():
    form = PostTypeForm()
    if form.validate_on_submit():
        posttype = PostType(
            name=form.name.data, explain=form.explain.data, ceate_id=current_user.id)
        db.session.add(posttype)
        flash("新增 "+posttype.name+" 博文归档")
        return redirect(url_for('.all_posttype'))
    return render_template('new_posttype.html', form=form)


@main.route('/posttype/update/<id>', methods=['GET', 'POST'])
@login_required
def update_posttype(id):
    form = PostTypeForm()
    posttype = PostType.query.get_or_404(id)
    if form.validate_on_submit():
        posttype.name = form.name.data
        posttype.explain = form.explain.data
        posttype.ceate_id = current_user.id
        db.session.add(posttype)
        flash("更新归档信息成功")
        return redirect(url_for('.all_posttype'))
    form.name.data = posttype.name
    form.explain.data = posttype.explain
    return render_template('edit_posttype.html', form=form, id=id)


@main.route('/all_type', methods=['GET', 'POST'])
def all_posttype():
    types = PostType.query.order_by(PostType.create_at.desc()).all()
    return render_template('all_types.html', types=types)


@main.route('/posttype/<id>', methods=['POST', 'GET'])
def posttype(id):
    form = SearchPosts()
    page = request.args.get('page', 1, type=int)
    type = PostType.query.get_or_404(id)
    pagination = Post.query.filter_by(posttype_id=type.id).order_by(Post.timestamp.desc(
    )).paginate(page, per_page=current_app.config['FLASKY_POSTS_PER_PAGE'], error_out=False)
    posts = pagination.items
    flash('所有 '+type.name+' 归档下的博文')
    return render_template('index.html', posts=posts, pagination=pagination, form=form)


@main.route('/posttype/delete/<id>', methods=['GET', 'POST'])
@admin_required
@login_required
def delete_posttype(id):
    posttype = PostType.query.get_or_404(id)
    if not posttype:
        flash('ID不存在')
        abort(404)
    else:
        db.session.delete(posttype)
        db.session.commit()
        flash("删除 "+posttype.name+" 归档成功")
    return redirect(url_for('.all_posttype'))


@main.route('/post/delete/<id>', methods=['GET', 'POST'])
# @login_required
def delete_post(id):
    post = Post.query.get_or_404(id)
    if current_user == post.author or current_user.can(Permission.ADMINISTER):
        db.session.delete(post)
        flash('删除博文成功')
    return redirect(url_for('.index'))


@main.route('/edit_profile', methods=['GET', 'POST'])
def edit_profile():
    form = EditProfileForm()
    if form.validate_on_submit():
        current_user.name = form.name.data
        current_user.location = form.location.data
        current_user.about_me = form.about_me.data
        db.session.add(current_user)
        flash("Your profile has been updated")
        return redirect(url_for('.user'), username=current_user.username)
    form.name.data = current_user.name
    form.location.data = current_user.location
    form.about_me.data = current_user.about_me
    return render_template('edit_profile.html', form=form)


@main.route('/edit-profile/<int:id>', methods=['GET', 'POST'])
@login_required
@admin_required
def edit_profile_admin(id):
    user = User.query.get_or_404(id)
    form = EditProfileAdminForm(user=user)
    if form.validate_on_submit():
        user.email = form.email.data
        user.username = form.username.data
        user.confirmed = form.confirmed.data
        user.role = Role.query.get(form.role.data)
        user.name = form.name.data
        user.location = form.location.data
        user.about_me = form.about_me.data
        db.session.add(user)
        flash('The profile has been updated.')
        return redirect(url_for('.user', username=user.username))
    form.email.data = user.email
    form.username.data = user.username
    form.confirmed.data = user.confirmed
    form.role.data = user.role_id
    form.name.data = user.name
    form.location.data = user.location
    form.about_me.data = user.about_me
    return render_template('edit_profile.html', form=form, user=user)


@main.route('/post/<int:id>', methods=['GET', 'POST'])
def post(id):
    post = Post.query.get_or_404(id)
    # 这里传递过去一个数组，本来foreach循环输出的，因为只有一个，所以只输出一个，所以为单个页面
    return render_template('post.html', post=post)


@main.route('/edit/<int:id>', methods=['GET', 'POST'])
@login_required
def edit(id):
    post = Post.query.get_or_404(id)
    if current_user != post.author and not current_user.can(Permission.ADMINISTER):
        abort(403)
    form = PostForm()
    if form.validate_on_submit():
        post.title = form.title.data
        post.content = form.content.data
        if form.posttype.data:
            post.posttype_id = form.posttype.data
        else:
            post.posttype_id = None
        post.last_timestamp = datetime.utcnow()  # 最后编辑时间
        db.session.add(post)
        flash('博客已更新')
        return redirect(url_for('main.post', id=post.id))
    form.posttype.data = post.posttype_id
    form.content.data = post.content
    form.title.data = post.title
    # mkd = post.body_html
    return render_template('edit_post.html', post=post, form=form)


@main.route('/new_post', methods=['GET', 'POST'])
@login_required
def new_post():
    if not current_user.can(Permission.WRITE_ARTICLES):
        abort(403)
    form = PostForm()
    if form.validate_on_submit():
        post = Post(title=form.title.data,
                    content=form.content.data,
                    author=current_user._get_current_object(),
                    )
        if form.posttype.data:
            post.posttype_id = form.posttype.data
        db.session.add(post)
        db.session.flush()  # 加上这个语句可以在 commit 之后获取到 id
        db.session.commit()
        # 有了新问题就提交一次索引
        # flask_whooshalchemyplus.index_one_model(Post)
        # post = Post.query.filter_by(title=post.title).first()
        flash('博客已发布')
        return redirect(url_for('.post', id=post.id))
    # form.content.data = """### 关于 Editor.md

    # ** Editor.md** 是一款开源的、可嵌入的 Markdown 在线编辑器（组件），基于 CodeMirror、jQuery 和 Marked 构建。"""
    return render_template('new_post.html', form=form)


@main.route('/follow/<username>')
@login_required
@permission_required(Permission.FOLLOW)
def follow(username):
    user = User.query.filter_by(username=username).first()
    if user is None:
        flash('Invalid user.')
        return redirect(url_for('.index'))
    if current_user.is_following(user):
        flash('您已经关注过了此用户了')
        return redirect(url_for('.user', username=username))
    current_user.follow(user)
    flash(f'成功关注用户{username}')
    return redirect(url_for('.user', username=username))


@main.route('/unfollow/<username>')
@login_required
@permission_required(Permission.FOLLOW)
def unfollow(username):
    user = User.query.filter_by(username=username).first()
    if user is None:
        flash('Invalid user.')
        return redirect(url_for('.index'))
    if not current_user.is_following(user):
        flash('You are not following this user.')
        return redirect(url_for('.user', username=username))
    current_user.unfollow(user)
    flash('You are not following %s anymore.' % username)
    return redirect(url_for('.user', username=username))


@main.route('/followers/<username>')
def followers(username):
    user = User.query.filter_by(username=username).first()
    if user is None:
        flash('Invalid user.')
        return redirect(url_for('.index'))
    page = request.args.get('page', 1, type=int)
    pagination = user.followers.paginate(
        page, per_page=current_app.config['FLASKY_FOLLOWERS_PER_PAGE'],
        error_out=False)
    follows = [{'user': item.follower, 'timestamp': item.timestamp}
               for item in pagination.items]
    return render_template('followers.html', user=user, title="Followers of",
                           endpoint='.followers', pagination=pagination,
                           follows=follows)


@main.route('/followed-by/<username>')
def followed_by(username):
    user = User.query.filter_by(username=username).first()
    if user is None:
        flash('Invalid user.')
        return redirect(url_for('.index'))
    page = request.args.get('page', 1, type=int)
    pagination = user.followed.paginate(
        page, per_page=current_app.config['FLASKY_FOLLOWERS_PER_PAGE'],
        error_out=False)
    follows = [{'user': item.followed, 'timestamp': item.timestamp}
               for item in pagination.items]
    return render_template('followers.html', user=user, title="Followed by",
                           endpoint='.followed_by', pagination=pagination,
                           follows=follows)


@main.route('/all')
@login_required
def show_all():
    resp = make_response(redirect(url_for('.index')))
    resp.set_cookie('show_followed', '', max_age=30*24*60*60)
    return resp


@main.route('/followed')
@login_required
def show_followed():
    resp = make_response(redirect(url_for('.index')))
    resp.set_cookie('show_followed', '1', max_age=30*24*60*60)
    return resp
